#include "stdafx.h"
#include "IniFile.h"

//-------------------------------------------------------------------------
// constructors
//-------------------------------------------------------------------------

CIniFile::CIniFile()
{
	m_nSections = 0;
	m_Elevation.nNumTextures = 0;
}

CIniFile::CIniFile(CString sPath)
{
	m_sPath = sPath;
}

//-------------------------------------------------------------------------
// destructor
//-------------------------------------------------------------------------

CIniFile::~CIniFile()
{
	m_vSection.~vector< Section >();
}

//-------------------------------------------------------------------------
// overloaded operators
//-------------------------------------------------------------------------

//-------------------------------------------------------------------------
// functions
//-------------------------------------------------------------------------

bool CIniFile::LoadIniFile()
{
	// Load file

	CStdioFile ioIniFile;

	if (!ioIniFile.Open(m_sPath, CFile::modeRead | CFile::shareExclusive)) return(false);

	// Dump old data

	m_vSection.clear();

	// Read through file

	CString sLineOfText;
	int nSectionIndex = -1;
	while (ioIniFile.ReadString(sLineOfText)) // grabs a line of text
	{
		CString sFirstChar = sLineOfText.Left(1);

		if (sFirstChar == ";" || 
			sFirstChar == "" || 
			sFirstChar == "/") // line is a comment or blank
		{
			continue; // skip to next line
		}
		else
		if (sFirstChar == "[") // line is a section name
		{
			Section tempSection;
			sLineOfText.TrimLeft("["); sLineOfText.TrimRight("]");
			tempSection.sSectionName = sLineOfText;
			m_vSection.push_back(tempSection);
			m_nSections += 1;
			nSectionIndex += 1;
		}
		else
		if (sFirstChar == "~") // line is a elevation texture
		{
			int nEnd;
			sLineOfText.TrimLeft("~");
			nEnd = sLineOfText.Find('\t');
			m_Elevation.sTexturePath.push_back(sLineOfText.Mid(0, nEnd));
			sLineOfText.Delete(0, nEnd+1);
			nEnd = sLineOfText.Find('\t');
			m_Elevation.fMinPct.push_back(atof(sLineOfText.Mid(0, nEnd)));
			sLineOfText.Delete(0, nEnd+1);
			nEnd = sLineOfText.GetLength();
			m_Elevation.fMaxPct.push_back(atof(sLineOfText.Mid(0, nEnd)));
			m_Elevation.nNumTextures += 1;
		}
		else // must be a key
		{
			int nStart, nEnd;
			CString sDataType, sKeyName, sKeyValue;

			// Extract data type
			
			nStart = sLineOfText.Find("(") + 1; nEnd = sLineOfText.Find(")");
			sDataType = sLineOfText.Mid(nStart, nEnd - nStart);
			m_vSection[nSectionIndex].vDataType.push_back(sDataType);

			// Extract the key name

			nStart = nEnd + 1; nEnd = sLineOfText.Find("=");
			sKeyName = sLineOfText.Mid(nStart, nEnd - nStart);
			m_vSection[nSectionIndex].vKey.push_back(sKeyName);

			// Extract the key value

			nStart = nEnd + 1; int nEndOfLine = sLineOfText.Find(" "); // allows comments for keys
			if (nEndOfLine < 0) nEnd = sLineOfText.GetLength();
			else nEnd = nEndOfLine;
			sKeyValue = sLineOfText.Mid(nStart, nEnd - nStart);
			m_vSection[nSectionIndex].vValue.push_back(sKeyValue);
		}
	}

	ioIniFile.Close();

return(true);
}

int CIniFile::ReadKey(CString sSection, CString sKey, float &fValue)
{
	if (m_nSections < 1) return(-1); // no ini file loaded yet

	// Find the section

	int nSectionNum = -1;
	for (int i=0; i<m_nSections; i++)
	{
		if (m_vSection[i].sSectionName == sSection)
		{
			nSectionNum = i;
			break;
		}
	}
	if (nSectionNum < 0) return(-2); // cannot find that section name

	// Find the key

	int nKeyNum = -1;
	for (i=0; i<m_vSection[nSectionNum].nNumKeys; i++)
	{
		if (m_vSection[nSectionNum].vKey[i] == sKey)
		{
			nKeyNum = i;
			break;
		}
	}
	if (nKeyNum < 0) return(-3); // cannot find that key

	// Stuff value into variable

	fValue = atof(m_vSection[nSectionNum].vValue[nKeyNum]);

return(0);
}

int CIniFile::ReadKey(CString sSection, CString sKey, int &nValue)
{
	if (m_nSections < 1) return(-1); // no ini file loaded yet

	// Find the section

	int nSectionNum = -1;
	for (int i=0; i<m_nSections; i++)
	{
		if (m_vSection[i].sSectionName == sSection)
		{
			nSectionNum = i;
			break;
		}
	}
	if (nSectionNum < 0) return(-2); // cannot find that section name

	// Find the key

	int nKeyNum = -1;
	for (i=0; i<m_vSection[nSectionNum].nNumKeys; i++)
	{
		if (m_vSection[nSectionNum].vKey[i] == sKey)
		{
			nKeyNum = i;
			break;
		}
	}
	if (nKeyNum < 0) return(-3); // cannot find that key

	// Stuff value into variable

	nValue = atoi(m_vSection[nSectionNum].vValue[nKeyNum]);

return(0);
}

int CIniFile::WriteSection(CString sSection)
{
	CStdioFile ioIniFile;

	if (!ioIniFile.Open(m_sPath, CFile::modeWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::shareExclusive)) return(false);
	ioIniFile.SeekToEnd();
	ioIniFile.WriteString("[" + sSection + "]" + "\n");
	ioIniFile.Close();

return(0);
}

int CIniFile::WriteKey(CString sKey, float &fValue)
{

	CStdioFile ioIniFile;
	CString sValue;

	if (!ioIniFile.Open(m_sPath, CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate | CFile::shareExclusive)) return(false);
	sValue.Format(_T("%.0f"), fValue);
	ioIniFile.SeekToEnd();
	ioIniFile.WriteString("(float)" + sKey + "=" + sValue + "\n");
	ioIniFile.Close();

return(0);
}

void CIniFile::DeleteIfExists()
{
	CStdioFile ioIniFile;
	ioIniFile.Open(m_sPath, CFile::modeCreate);
	ioIniFile.Close();
}